package com.yang.sso.oauth.oauth;


import com.yang.sso.oauth.oauth.exception.ResponseExceptionTranslator;
import com.yang.sso.oauth.userdetails.MyUserDetailsServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
import org.springframework.security.oauth2.provider.TokenGranter;
import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * 授权服务器Oauth2配置
 * @author: Islands
 * @create: 2024-04-11 20:08
 */


@Configuration
@RequiredArgsConstructor
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {


    private final AuthenticationManager authenticationManager;
    private final MyUserDetailsServiceImpl myUserDetailsService;
    private final JdbcClientDetailsService jdbcClientDetailsService;
    private final TokenStore tokenStore;
    private final AuthorizationCodeServices authorizationCodeServices;
    private final JdbcApprovalStore approvalStore;
//    private final TokenEnhancer tokenEnhancer;

    private final JwtAccessTokenConverter jwtAccessTokenConverter;

    /**
     *  配置令牌端点的安全约束
     * @param security a fluent configurer for security features
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                // /oauth/token_key 公开
                .tokenKeyAccess("permitAll()")
                // /oauth/check_token 公开
                .checkTokenAccess("permitAll()")
                //表单认证，申请令牌
                .allowFormAuthenticationForClients();
    }



    /**
     *  oauth_client_details 表的查询
     *  配置客户端详情(客户端详情信息在这里初始化)
     * @param clients the client details configurer
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService);
    }


    /**
     * 配置令牌的访问端点
     * @param endpoints the endpoints configurer
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints
                //认证管理器
                .authenticationManager(authenticationManager)
                //授权模式
                .tokenGranter(tokenGranter(endpoints))
                //授权码储存策略
                .authorizationCodeServices(authorizationCodeServices)
                //储存已授权用户
                .approvalStore(approvalStore)
                //密码模式的用户信息管理器
                .userDetailsService(myUserDetailsService)
                //令牌管理服务
                .tokenServices(tokenServices())
                .allowedTokenEndpointRequestMethods(HttpMethod.OPTIONS)
                //转换器异常
                .exceptionTranslator(new ResponseExceptionTranslator())
                ;
    }

    /**
     * 授权扩展模式
     * @param endpoints
     * @return
     */
    private TokenGranter tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints) {
        List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
        // 添加验证码授权模式授权者
//        granterList.add(new SmsCodeTokenGranter(endpoints.getTokenServices(),
//                endpoints.getClientDetailsService(),
//                endpoints.getOAuth2RequestFactory()
//        ));
        return new CompositeTokenGranter(granterList);
    }

    @Bean
    public AuthorizationServerTokenServices tokenServices(){
        DefaultTokenServices services = new DefaultTokenServices();
        //客户端详情服务
        services.setClientDetailsService(jdbcClientDetailsService);
        //令牌储存策略
        services.setTokenStore(tokenStore);
        //在令牌储存策略 之上加一个 jwt 令牌策略
        services.setTokenEnhancer(jwtAccessTokenConverter);
        //否产生刷新令牌
        services.setSupportRefreshToken(true);
        //令牌有效期(默认2小时)
        //services.setAccessTokenValiditySeconds(7200);
        //刷新令牌有效期(默认3天)
        //services.setRefreshTokenValiditySeconds(259200);
        return services;
    }



}
